
/*
 * Project Name: yum-sample
 * File Name: DateUtil.java
 * Class Name: DateUtil
 *
 * Copyright 2018 Hengtian Software Inc
 *
 * Licensed under the Hengtiansoft
 *
 * http://www.hengtiansoft.com
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.magical.normal.utils;

import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.helpers.MessageFormatter;
import org.springframework.util.StringUtils;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * Description: 时间工具类
 *
 * @author qianqianzhu1, weiyangzhu
 * @since 13.06.2018
 */
public final class DateUtil {

    public static final String SIMPLE_FMT = "yyyy-MM-dd HH:mm:ss";
    public static final String SIMPLE_FMT_MINUTE = "yyyy-MM-dd HH:mm";
    public static final String SIMPLE_YMD = "yyyy-MM-dd";
    public static final String SIMPLE_FMT_ZH = "yyyy年MM月dd日";
    public static final String SIMPLE_FMT_M = "yyyy年MM月";
    public static final String SIMPLE_DATE_YMD = "yyyyMMdd";
    public static final String SIMPLE_MDY = "MM/dd/yyyy";
    public static final String DATE_PATTERN_FULL = "yyyyMMddHHmmss";
    public static final String DATE_PATTERN_YEAR = "yyMMddHHmmss";
    public static final String SIMPLE_FMT_NOSPACE = "yyyyMMddHHmm";
    public static final String SIMPLE_FMT_SSS = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String SIMPLE_FMT_MONTH = "yyyyMM";
    public static final String SIMPLE_YM = "yyyy-MM";
    public static final String SIMPLE_YMD_SPLIT_VIRGULE = "yyyy/MM/dd";
    public static final String SIMPLE_FMT_SPLIT_VIRGULE = "yyyy/MM/dd HH:mm";
    public static final String SIMPLE_FMT_FULL_ZH = "yyyy年MM月dd日 HH:mm:ss";
    public static final String SIMPLE_FMT_SPLIT_VIRGULE_SIMPLE = "M/d/yyyy h:m";
    public static final String SIMPLE_FMT_SPLIT_SIMPLE = "M/d/yyyy";

    public static final String TIME_ZONE_CHINA = "GMT+8";

    public static final int DEFAULT_END_HOUR = 23;
    public static final int DEFAULT_END_MINUTE = 59;
    public static final int DEFAULT_END_SENCEND = 59;
    public static final int DEFAULT_END_MIN_SENCEND = 000;
    public static final int DEFAULT_MONTH_OF_YEAR = 12;

    public static final ZoneId ZONE_ID = ZoneId.systemDefault();

    private static final Logger LOGGER = LoggerFactory.getLogger(DateUtil.class);

    public static final int DEFAULT_HOUR = 23;

    public static final int DEFAULT_MINUTE = 59;

    public static final int DEFAULT_SENCEND = 0;

    private DateUtil() {

    }

    /**
     * 时间转换Date to String
     *
     * @param date    日期
     * @param sFormat 对应日期格式
     * @return 字符串形式的日期时间
     */
    public static String dateToString(Date date, String sFormat) {
        return date == null || StringUtils.isEmpty(sFormat) ? null : FastDateFormat.getInstance(sFormat).format(date);
    }

    /**
     * 时间转换String to Date
     *
     * @param sDate   源字符串
     * @param sFormat 对应日期格式
     * @return Date类型
     */
    public static Date stringToDate(String sDate, String sFormat) {
        try {
            FastDateFormat fastDateFormat = FastDateFormat.getInstance(sFormat);
            return fastDateFormat.parse(sDate);
        } catch (ParseException e) {
            LOGGER.error("Parse date exception", e);
            throw new RuntimeException(e); // NOSONAR, convert exception to runtimeexception
        }
    }

    /**
     * 字符串转换为时间，支持多种可选格式
     *
     * @param sDate   源字符串
     * @param formats 可能对应的日期格式
     * @return Date类型
     */
    public static Date stringToDate(String sDate, String... formats) {
        Date date = null;
        for (String format : formats) {
            try {
                date = DateUtil.stringToDate(sDate, format);
                if (date != null) {
                    break;
                }
            } catch (RuntimeException e) {
                // ignore exception
            }
        }
        if (date == null) {
            throw new RuntimeException(MessageFormatter.format("使用格式{}解析日期{}出现异常", formats, sDate).getMessage());
        }
        return date;
    }

    /**
     * 传入TimeStamp类型日期转换为String类型
     *
     * @param timestamp 源timestamp
     * @param sFormat   对应日期格式
     * @return 格式化后的时间戳
     */
    public static String timeStampToString(Timestamp timestamp, String sFormat) {
        return new SimpleDateFormat(sFormat).format(timestamp);
    }

    /**
     * 传入String类型日期转换为Timestamp类型
     *
     * @param sTimestamp sTimestamp
     * @param sFormat    对应日期格式
     * @return 时间戳类型
     */
    public static Timestamp timeStampParse(String sTimestamp, String sFormat) {
        return Timestamp.valueOf(dateToString(stringToDate(sTimestamp, sFormat), sFormat));
    }

    /**
     * 获取指定日期几天后的日期
     */
    public static String getDateAfterDays(String dateStr, Integer days, String strFormat) {
        if (StringUtils.isEmpty(dateStr)) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();// 日历对象
        calendar.setTime(stringToDate(dateStr, strFormat));
        calendar.add(Calendar.DATE, days);
        return dateToString(calendar.getTime(), strFormat);// 输出格式化的日期
    }

    /**
     * 获取指定日期几天后的日期
     */

    public static Date getDateAfterDays(Date date, Integer days) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();// 日历对象
        calendar.setTime(date);
        calendar.add(Calendar.DATE, days);
        return calendar.getTime();
    }

    /**
     * 获取指定日期几小时后的日期
     */

    public static Date getDateAfterHours(Date date, Integer hours) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();// 日历对象
        calendar.setTime(date);
        calendar.add(Calendar.HOUR, hours);
        return calendar.getTime();
    }

    /**
     * 将日期转换为中文字符串
     *
     * @param date 日期
     * @return 中文日期字符串
     */
    public static String parseDateToMString(Date date) {
        return dateToString(date, SIMPLE_FMT_M);
    }

    /**
     * 将日期转换为中文字符串
     *
     * @param date 日期
     * @return 中文日期字符串
     */
    public static String parseDateToZHString(Date date) {
        return dateToString(date, SIMPLE_FMT_ZH);
    }

    /**
     * 将yyyy-MM-dd转化为Date
     *
     * @param s 日期字符串
     * @return Date类型
     */
    public static Date timeStampParseYear(String s) {
        return stringToDate(s, SIMPLE_YMD);
    }

    /**
     * 将时间新增或减少对应月份
     *
     * @param dt     时间
     * @param amount 减少月份数
     * @return Date类型
     */
    public static Date subMonth(Date dt, int amount) {
        if (dt == null) {
            return null;
        }
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(dt);
        rightNow.add(Calendar.MONTH, amount);
        return rightNow.getTime();
    }

    /**
     * @return 当前时间的 yyyyMMddHHmmss str
     */
    public static String getCurrentTimeStr() {
        return dateToString(new Date(), DATE_PATTERN_FULL);
    }

    /**
     * 日期转毫秒数
     *
     * @param date date
     * @return 毫秒数
     */
    public static Long getTimeInMillis(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getTimeInMillis();
    }

    /**
     * 判断两个日期是否是同一个月
     *
     * @param date1
     * @param date2
     * @return
     */
    public static boolean checkTheSameMonth(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            return false;
        }
        Calendar c1 = Calendar.getInstance();
        c1.setTime(date1);
        Calendar c2 = Calendar.getInstance();
        c2.setTime(date2);
        return c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR) && c1.get(Calendar.MONTH) == c2.get(Calendar.MONTH);
    }

    /**
     * 返回某月第一天
     *
     * @param date
     * @return
     */
    public static Date getFirstDayOfMonth(Date date) {
        if (date == null) {
            return null;
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.DAY_OF_MONTH, 1);
        return c.getTime();
    }

    /**
     * 返回某月最后一天
     *
     * @param date
     * @return
     */
    public static Date getLastDayOfMonth(Date date) {
        if (date == null) {
            return null;
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int lastDay = c.getActualMaximum(Calendar.DATE);
        c.set(Calendar.DAY_OF_MONTH, lastDay);
        return c.getTime();
    }

    /**
     * @param paymentDay 201812   yyyy-MM-dd HH:mm:ss
     * @return 获取这个月第一天0秒
     */
    public static String getFirstDayTimeByPaymentDay(String paymentDay) {
        return paymentDay.substring(0, 4) + "-" + paymentDay.substring(4, 6) + "-01 00:00:00";
    }

    /**
     * @param date 201812  yyyy-MM-dd HH:mm:ss
     * @return 获取这个月第一天0秒
     */
    public static Date getFirstDayTimeByPaymentDay(Date date) {
        return DateUtil.stringToDate(getFirstDayTimeByPaymentDay(DateUtil.dateToString(date, SIMPLE_FMT_MONTH)), SIMPLE_FMT);
    }

    /**
     * @param paymentDay 201812  yyyy-MM-dd HH:mm:ss
     * @return 获取这个月最后一天59秒
     */
    public static String getLastDayTimeByPaymentDay(String paymentDay) {
        return DateUtil.getLastDayOfMonth(DateUtil.stringToDate(paymentDay, SIMPLE_FMT_MONTH), SIMPLE_YMD) + " 23:59:59";
    }

    /**
     * 获取这个月最后一天
     *
     * @param paymentDay
     * @return
     */
    public static String getLastDayMonthByPaymentDay(String paymentDay) {
        return DateUtil.getLastDayOfMonth(DateUtil.stringToDate(paymentDay, SIMPLE_FMT_MONTH), SIMPLE_YMD);
    }

    /**
     * @param date 201812  yyyy-MM-dd HH:mm:ss
     * @return 获取这个月最后一天59秒
     */
    public static Date getLastDayTimeByPaymentDay(Date date) {
        return DateUtil.stringToDate(getLastDayTimeByPaymentDay(DateUtil.dateToString(date, SIMPLE_FMT_MONTH)), SIMPLE_FMT);
    }

    /**
     * 按照给定格式返回某月第一天
     *
     * @param date
     * @param fm
     * @return
     */
    public static String getFirstDayOfMonth(Date date, String fm) {
        return new SimpleDateFormat(fm).format(getFirstDayOfMonth(date));
    }

    /**
     * 按照给定格式返回某月最后一天
     *
     * @param date
     * @param fm
     * @return
     */
    public static String getLastDayOfMonth(Date date, String fm) {
        return new SimpleDateFormat(fm).format(getLastDayOfMonth(date));
    }

    /**
     * Description: 智能格式化数据，如果时分秒为空，去除十分秒
     *
     * @param date
     * @return
     */
    public static String smartDateToString(Date date, String sFormat) {
        return dateToString(date, sFormat).replace(" 00:00:00", "");
    }

    /**
     * Description: 转换LocalDateTime 到Date
     *
     * @param ldt LocalDateTime
     * @return Date
     */
    public static Date LocalDateTimeToDate(LocalDateTime ldt) {
        if (ldt == null) {
            return null;
        }
        return Date.from(ldt.atZone(ZONE_ID).toInstant());
    }

    /**
     * Description: 转换Date 到LocalDateTime
     *
     * @param date
     * @return
     */
    public static LocalDateTime dateToLocalDateTime(Date date) {
        if (date == null) {
            return null;
        }
        return date.toInstant().atZone(ZONE_ID).toLocalDateTime();
    }

    /**
     * Description: 转换Date 到LocalDate
     *
     * @param date
     * @return
     */
    public static LocalDate dateToLocalDate(Date date) {
        if (date == null) {
            return null;
        }
        return date.toInstant().atZone(ZONE_ID).toLocalDate();
    }

    /**
     * Description: 转换LocalDate 到Date
     *
     * @param ld LocalDate
     * @return Date
     */
    public static Date LocalDateToDate(LocalDate ld) {
        if (ld == null) {
            return null;
        }
        return Date.from(ld.atStartOfDay().atZone(ZONE_ID).toInstant());
    }

    /**
     * Description: 取日期为一个月的第几天
     *
     * @param date
     * @return
     */
    public static int getDateOfMonth(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取@date 的下一个工作日
     *
     * @param date     时间
     * @param holidays 节假日集合
     * @return 下个工作日
     */
    public static LocalDate getNextWorkDay(LocalDate date, List<LocalDate> holidays) {
        if (holidays == null) {
            holidays = new ArrayList<>();
        }
        if (date == null) {
            return null;
        }
        date = date.plusDays(1);
        while (date.getDayOfWeek() == DayOfWeek.SATURDAY || date.getDayOfWeek() == DayOfWeek.SUNDAY
                || holidays.indexOf(date) > -1) {
            date = date.plusDays(1);
        }
        return date;
    }

    /**
     * 如果当前时间是节假日，返回下一个工作日
     *
     * @param date     时间
     * @param holidays 节假日集合
     * @return 下个工作日
     */
    public static LocalDate getOpWorkDay(LocalDate date, List<LocalDate> holidays) {
        if (holidays == null) {
            holidays = new ArrayList<>();
        }
        if (date == null) {
            return null;
        }
        while (date.getDayOfWeek() == DayOfWeek.SATURDAY || date.getDayOfWeek() == DayOfWeek.SUNDAY
                || holidays.indexOf(date) > -1) {
            date = date.plusDays(1);
        }
        return date;
    }

    public static List<LocalDate> getPeriodDates(LocalDate preDate, LocalDate finalDate, List<LocalDate> dateList) {
        if (dateList == null) {
            dateList = new ArrayList<>();
        }
        if (preDate.compareTo(finalDate) > 0) {
            throw new IllegalArgumentException("参数异常");
        }
        while (preDate.compareTo(finalDate) <= 0) {
            dateList.add(preDate);
            preDate = preDate.plusDays(1);
        }
        return dateList;
    }

    public static LocalDate getCurrentSunDay(LocalDate date) {
        while (date.getDayOfWeek() != DayOfWeek.SUNDAY) {
            date = date.plusDays(1);
        }
        return date;
    }

    public static Long getDelay(Date preDate, Date finalDate) {
        if (preDate == null || finalDate == null) {
            return null;
        }
        LocalDate preLocalDate = preDate.toInstant().atZone(ZONE_ID).toLocalDate();
        LocalDate finalLocalDate = finalDate.toInstant().atZone(ZONE_ID).toLocalDate();
        return finalLocalDate.toEpochDay() - preLocalDate.toEpochDay();
    }

    public static Date getNextDate(String dateTime, int days) {
        Date date = DateUtil.stringToDate(dateTime, DateUtil.SIMPLE_YMD);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, days);
        return cal.getTime();
    }

    public static Date plusYears(Date date, int amount) {
        return plus(date, Calendar.YEAR, amount);
    }

    public static Date plusMonths(Date date, int amount) {
        return plus(date, Calendar.MONTH, amount);
    }

    public static Date plusDays(Date date, int amount) {
        return plus(date, Calendar.DATE, amount);
    }

    public static Date plusHours(Date date, int amount) {
        return plus(date, Calendar.HOUR, amount);
    }

    public static Date plusMinutes(Date date, int amount) {
        return plus(date, Calendar.MINUTE, amount);
    }

    public static Date plusSeconds(Date date, int amount) {
        return plus(date, Calendar.SECOND, amount);
    }

    public static Date plusMilliseconds(Date date, int amount) {
        return plus(date, Calendar.MILLISECOND, amount);
    }

    private static Date plus(Date date, int field, int amount) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(field, amount);
        return calendar.getTime();
    }

    /**
     * 获取年份
     *
     * @param date 日期
     * @return 年份
     */
    public static int getYear(Date date) {
        return getPart(date, Calendar.YEAR);
    }

    /**
     * 获取月份
     *
     * @param date 日期
     * @return 月份
     */
    public static int getMonth(Date date) {
        return getPart(date, Calendar.MONTH) + 1;
    }

    /**
     * 获取天数
     *
     * @param date 日期
     * @return 天数
     */
    public static int getDay(Date date) {
        return getPart(date, Calendar.DATE);
    }

    /**
     * 获取星期
     *
     * @param date 日期
     * @return 星期数
     */
    public static int getDayOfWeek(Date date) {
        int day = getPart(date, Calendar.DAY_OF_WEEK) - 1;
        return day == 0 ? 7 : day;
    }

    /**
     * 获取月份中的天数
     *
     * @param date 日期
     * @return 月份中的天数
     */
    public static int getDayOfMonth(Date date) {
        return getPart(date, Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取年份中的天数
     *
     * @param date 日期
     * @return 年份中的天数
     */
    public static int getDayOfYear(Date date) {
        return getPart(date, Calendar.DAY_OF_YEAR);
    }

    private static int getPart(Date date, int type) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(type);
    }

    /**
     * 描述: 设置当天结束时间
     *
     * @param date
     * @return
     */
    public static Date setDefaultEndDate(Date date) {
        date = DateUtils.setHours(date, DEFAULT_HOUR);
        date = DateUtils.setMinutes(date, DEFAULT_MINUTE);
        date = DateUtils.setSeconds(date, DEFAULT_MINUTE);
        return date;
    }

    public static Long rangeTime(Date startTime, Date endTime, Integer seekType) {

        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(startTime);
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(endTime);

        Calendar temp = Calendar.getInstance();
        temp.setTime(endTime);
        temp.add(Calendar.DATE, 1);

        int year = endCalendar.get(Calendar.YEAR) - startCalendar.get(Calendar.YEAR);
        int month = endCalendar.get(Calendar.MONTH) - startCalendar.get(Calendar.MONTH);

        // 获取结束时间戳
        switch (seekType) {
            case Calendar.YEAR:
                return (long) year;
            case Calendar.MONTH:

                if ((startCalendar.get(Calendar.DATE) == 1) && (temp.get(Calendar.DATE) == 1)) {
                    return (long) (year * DEFAULT_MONTH_OF_YEAR + month + 1);
                } else if ((startCalendar.get(Calendar.DATE) != 1) && (temp.get(Calendar.DATE) == 1)) {
                    return (long) (year * DEFAULT_MONTH_OF_YEAR + month);
                } else if ((startCalendar.get(Calendar.DATE) == 1) && (temp.get(Calendar.DATE) != 1)) {
                    return (long) (year * DEFAULT_MONTH_OF_YEAR + month);
                } else {
                    return (long) ((year * DEFAULT_MONTH_OF_YEAR + month - 1) < 0 ? 0
                            : (year * DEFAULT_MONTH_OF_YEAR + month));
                }

            case Calendar.DATE:
                // 60 * 60 * 24 * 1000 = 86400000‬
                return (endTime.getTime() - startTime.getTime()) / (86400000);

            default:
                return null;
        }
    }


    public static Long currentDayInitMills() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime().getTime();
    }

    /**
     * 返回某月第一天的开始 2020-11-01 00:00:00
     *
     * @param date 给定日期
     * @return 月第一天第0秒
     */
    public static Date getFirstDayStartOfMonth(Date date) {
        return stringToDate(getFirstDayOfMonth(date, "yyyy-MM-dd 00:00:00"), SIMPLE_FMT);
    }

    public static Date getFirstDayStartOfMonth(String date, String fmt) {
        return stringToDate(getFirstDayOfMonth(stringToDate(date, fmt), "yyyy-MM-dd 00:00:00"), SIMPLE_FMT);
    }

    /**
     * 返回某月最后一天的结束 2020-11-30 23:59:59
     *
     * @param date 给定日期
     * @return 月最后一天最后一秒
     */
    public static Date getLastDayEndOfMonth(Date date) {
        return stringToDate(getLastDayOfMonth(date, "yyyy-MM-dd 23:59:59"), SIMPLE_FMT);
    }

    public static Date getLastDayEndOfMonth(String date, String fmt) {
        return stringToDate(getLastDayOfMonth(stringToDate(date, fmt), "yyyy-MM-dd 23:59:59"), SIMPLE_FMT);
    }

    public static Date getStartOfDate(String date, String fmt) {
        Calendar calendar = Calendar.getInstance();// 日历对象
        calendar.setTime(stringToDate(date, fmt));
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getStartOfDate(Date date) {
        Calendar calendar = Calendar.getInstance();// 日历对象
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getEndOfDate(String date, String fmt) {
        Calendar calendar = Calendar.getInstance();// 日历对象
        calendar.setTime(stringToDate(date, fmt));
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar.getTime();
    }

    public static Date getEndOfDate(Date date) {
        Calendar calendar = Calendar.getInstance();// 日历对象
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar.getTime();
    }

    /**
     * 根据一段时间获取该段时间的所有日期  倒序排序
     *
     * @param startDate
     * @param endDate
     * @return yyyy-MM-dd
     */
    public static List<String> getTwoDaysDay(String startDate, String endDate) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        List<String> dateList = new ArrayList<String>();
        try {
            Date dateOne = sdf.parse(startDate);
            Date dateTwo = sdf.parse(endDate);

            Calendar calendar = Calendar.getInstance();
            calendar.setTime(dateTwo);

            dateList.add(endDate);
            while (calendar.getTime().after(dateOne)) { //倒序时间,顺序after改before其他相应的改动。
                calendar.add(Calendar.DAY_OF_MONTH, -1);
                dateList.add(sdf.format(calendar.getTime()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dateList;
    }

    /**
     * 根据一段时间获取该段时间的所有日期  正序排序
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static List<String> getTwoDaysDayDes(String startDate, String endDate) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        List<String> dateList = new ArrayList<String>();
        try {
            Date dateOne = sdf.parse(startDate);
            Date dateTwo = sdf.parse(endDate);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(dateOne);
            dateList.add(startDate);
            while (dateTwo.after(calendar.getTime())) {
                calendar.add(Calendar.DAY_OF_MONTH, 1);
                dateList.add(sdf.format(calendar.getTime()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dateList;
    }

    /**
     * 获取某段时间内的所有日期
     *
     * @param startDate yyyy-MM-dd
     * @param endDate   yyyy-MM-dd
     * @return yyyy-MM-dd
     */
    public static List<Date> findDates(Date startDate, Date endDate) {
        Calendar cStart = Calendar.getInstance();
        cStart.setTime(startDate);

        List dateList = new ArrayList();
        //别忘了，把起始日期加上
        dateList.add(startDate);
        // 此日期是否在指定日期之后
        while (endDate.after(cStart.getTime())) {
            // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
            cStart.add(Calendar.DAY_OF_MONTH, 1);
            dateList.add(cStart.getTime());
        }
        return dateList;
    }

    /**
     * 根据一段时间获取该段时间的所有月份
     *
     * @param minDate yyyy-MM
     * @param maxDate yyyy-MM
     * @return
     */
    public static List<String> getMonthBetween(String minDate, String maxDate) {
        ArrayList<String> result = new ArrayList<String>();
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");//格式化为年月

            Calendar min = Calendar.getInstance();
            Calendar max = Calendar.getInstance();
            min.setTime(sdf.parse(minDate));
            min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);

            max.setTime(sdf.parse(maxDate));
            max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);

            Calendar curr = min;
            while (curr.before(max)) {
                result.add(sdf.format(curr.getTime()));
                curr.add(Calendar.MONTH, 1);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 时间进行切割
     *
     * @param beginTime
     * @param endTime
     * @return
     * @throws ParseException
     */
    public static List<String> splitDateByDay(String beginTime, String endTime) {
        List<String> allDate = null;
        try {
            allDate = new ArrayList();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date dBegin = sdf.parse(beginTime);
            Date dEnd = sdf.parse(endTime);
            allDate.add(sdf.format(dBegin));
            Calendar calBegin = Calendar.getInstance();
            // 使用给定的 Date 设置此 Calendar 的时间
            calBegin.setTime(dBegin);
            Calendar calEnd = Calendar.getInstance();
            // 使用给定的 Date 设置此 Calendar 的时间
            calEnd.setTime(dEnd);
            // 测试此日期是否在指定日期之后
            while (dEnd.after(calBegin.getTime())) {
                // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
                calBegin.add(Calendar.DAY_OF_MONTH, 1);
                allDate.add(sdf.format(calBegin.getTime()));
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return allDate;
    }

    /**
     * 根据指定时间获取任意月后的时间
     * time 指定的时间  mon 1表示后一个月 -1表示前一个月
     */
    public static String getMon(String time, int mon) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        try {
            calendar.setTime(sdf.parse(time));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        calendar.add(Calendar.MONTH, mon);
        String date = sdf.format(calendar.getTime());
        return date;
    }

    /**
     * 计算相差的月份
     *
     * @param largeDate
     * @param smallDate
     * @return
     */
    public static int getMonthDiff(Date largeDate, Date smallDate) {
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(largeDate);
        c2.setTime(smallDate);
        int year1 = c1.get(Calendar.YEAR);
        int year2 = c2.get(Calendar.YEAR);
        int month1 = c1.get(Calendar.MONTH);
        int month2 = c2.get(Calendar.MONTH);
        // 获取年的差值
        int yearInterval = year1 - year2;
        // 获取月数差值
        int monthInterval = month1 - month2;
        int monthsDiff = yearInterval * 12 + monthInterval;
        return monthsDiff;
    }

    /**
     * 获取两个日期之间的所有月份 (年月)
     *
     * @param startTime
     * @param endTime
     * @return：YYYY-MM
     */
    public static List<String> getMonthBetweenDate(String startTime, String endTime) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        // 声明保存日期集合
        List<String> list = new ArrayList<String>();
        try {
            // 转化成日期类型
            Date startDate = sdf.parse(startTime);
            Date endDate = sdf.parse(endTime);

            //用Calendar 进行日期比较判断
            Calendar calendar = Calendar.getInstance();
            while (startDate.getTime() <= endDate.getTime()) {
                // 把日期添加到集合
                list.add(sdf.format(startDate));
                // 设置日期
                calendar.setTime(startDate);
                //把日期增加一天
                calendar.add(Calendar.MONTH, 1);
                // 获取增加后的日期
                startDate = calendar.getTime();
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 返回某天的上月最后一天的结束 2020-11-30 23:59:59
     *
     * @param checktime 给定日期
     * @return 月最后一天最后一秒
     */
    public static Date getLastDayEndOfLastMonth(String checktime, String format) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
        LocalDate date = LocalDate.parse(checktime, formatter);

        // 获取上个月的最后一天
        LocalDate lastDayOfPreviousMonth = date.with(TemporalAdjusters.firstDayOfMonth()).minusDays(1);
        // 获取上个月最后一天的最后一秒
        LocalDateTime lastSecondOfPreviousMonth = lastDayOfPreviousMonth.atTime(23, 59, 59);

        return Date.from(lastSecondOfPreviousMonth.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static Date getLastDayEndOfLastMonthForDate(Date firstDayStartOfMonth) {
        LocalDate date = dateToLocalDate(firstDayStartOfMonth);
        // 获取上个月的最后一天
        LocalDate lastDayOfPreviousMonth = date.with(TemporalAdjusters.firstDayOfMonth()).minusDays(1);
        // 获取上个月最后一天的最后一秒
        LocalDateTime lastSecondOfPreviousMonth = lastDayOfPreviousMonth.atTime(23, 59, 59);

        return Date.from(lastSecondOfPreviousMonth.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static void main(String[] args) {
        String startStr = "2021-02";
        String endStr = "2021-03";
        List<String> list = getMonthBetweenDate(startStr, endStr);
        System.out.println(list);
    }

}

